// -------------------------------------------------------------
// [check_tdl] inspect its attribute and values after parsing the given tdl
//
// Author : Woo-Hyun Kim
// Email : woorung@icu.ac.kr or woorung@nhncorp.com
// Date : Aug. 30, 2006
// -------------------------------------------------------------
#include <iostream>
#include <iterator>
#include <vector>
#include <list>
#include <algorithm>
#include <fstream>
#include <string>

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#include "CInfoMap.h"

int check_variables(vector<Tattr_val> &attr_val);
int check_action(Taction &action);
int check_invoker(Tinvoker &invoker);


CInfoMap *im = NULL;
Tinfo_map *info_map = NULL;

int check_common_task_block(string &tdl_fname)
{
	if(im==NULL) {
		im = new CInfoMap((char *)tdl_fname.c_str());
		info_map = im->getIMap();
	}

	cout << "[common task block] ---------------------------" << endl;

	check_variables(info_map->common_task.attr_val);

	cout << "-----------------------------------------------" << endl;
	cout << endl;

	if(im!=NULL) {
		delete im;
		im = NULL;
	}
}

int check_task_block(string &tdl_fname, string &task_name)
{
	if(im==NULL) {
		im = new CInfoMap((char *)tdl_fname.c_str());
		info_map = im->getIMap();
	}

	cout << "/// " << task_name << " ///"  << endl;
	cout << "[task block] ----------------------------------" << endl;

	for(int i=0;i<info_map->tasks.size();i++) {
		if(task_name==info_map->tasks[i].name) {
			check_variables(info_map->tasks[i].attr_val);

			for(int j=0;j<info_map->tasks[i].actions.size();j++) {
				check_action(info_map->tasks[i].actions[j]);
			}

			for(int j=0;j<info_map->tasks[i].invokers.size();j++) {
				check_invoker(info_map->tasks[i].invokers[j]);
			}
		}
	}

	cout << "-----------------------------------------------" << endl;
	cout << endl;

	if(im!=NULL) {
		delete im;
		im = NULL;
	}
}

int check_variables(vector<Tattr_val> &attr_val)
{
    cout << "<external variables>" << endl;
    // external variables(environment variables)
    for(int i=0;i<attr_val.size();i++) {
        if(attr_val[i].attr[0]=='@') continue;

        cout << "\t" << attr_val[i].attr;
        cout << "=";
        cout << attr_val[i].val;
        cout << endl;
    }
    cout << endl;

    cout << "<internal variables>" << endl;
    // internal variables(system-level variables)
    for(int i=0;i<attr_val.size();i++) {
        if(attr_val[i].attr[0]!='@') continue;

        cout << "\t" << attr_val[i].attr;
        cout << "=";
        cout << attr_val[i].val;
        cout << endl;
    }
	cout << endl;
}

int check_action(Taction &action)
{
	cout << "<external action>" << action.name << endl;

	for(int i=0;i<action.commands.size();i++) {
		cout << "\t" << action.commands[i] << endl;
	}
}

int check_invoker(Tinvoker &invoker)
{
	cout << "<internal action>" << invoker.name << endl;

	map<string,string>::iterator param = invoker.params.begin();
	while(param!=invoker.params.end()) {
		cout << "\t" << param->first << "=" << param->second << endl;
		param++;
	}
	cout << endl;
}

int check_action_block(string &tdl_fname, string &action_name)
{
	if(im==NULL) {
		im = new CInfoMap((char *)tdl_fname.c_str());
		info_map = im->getIMap();
	}

	cout << "/// " << action_name << " ///"  << endl;
	cout << "[action block] ----------------------------------" << endl;

	for(int i=0;i<info_map->tasks.size();i++) {
		for(int j=0;j<info_map->tasks[i].actions.size();j++) {
			if(action_name==info_map->tasks[i].actions[j].name) {
				check_action(info_map->tasks[i].actions[j]);
			}
		}

		for(int j=0;j<info_map->tasks[i].invokers.size();j++) {
			if(action_name==info_map->tasks[i].invokers[j].name) {
				check_invoker(info_map->tasks[i].invokers[j]);
			}
		}
	}

	cout << "------------------------------------------------" << endl;
	cout << endl;

	if(im!=NULL) {
		delete im;
		im = NULL;
	}
}

int check_all(string &tdl_fname)
{
	if(im==NULL) {
		im = new CInfoMap((char *)tdl_fname.c_str());
		info_map = im->getIMap();
	}

	cout << "/// " << tdl_fname << " ///" << endl;
	check_common_task_block(tdl_fname);

	for(int i=0;i<info_map->tasks.size();i++) {
		string target_task = info_map->tasks[i].name;
		check_task_block(tdl_fname, target_task);
	}

	if(im!=NULL) {
		delete im;
		im = NULL;
	}
}

void print_usage(char *argv[])
{
	cout << "usage : " << argv[0] << " [option] <tdl file>" << endl;
	cout << "\t-c\t\t" << "check common task variables" << endl;
	cout << "\t-t <task name>\t" << "check a given task block" << endl;
	cout << "\t-a <action name>\t" << "check a given action block" << endl;

	exit(-1);
}

int main(int argc, char *argv[])
{
	if(argc<2) print_usage(argv);

	int opt;
	static char optstr[] = "cta";

	while((opt=getopt(argc,argv,optstr))!=-1) {
		switch(opt) {
			case 'c' : 
			{
				// check in the common task block;
				if(optind>=argc) print_usage(argv);
				string tdl_fname = argv[optind];
				check_common_task_block(tdl_fname);
				return 1;
				break;
			}
			case 't' :
			{
				// check in the given task block;
				if(optind>=argc) print_usage(argv);
				string task_name = argv[optind++];
				if(optind>=argc) print_usage(argv);
				string tdl_fname = argv[optind];
				check_task_block(tdl_fname, task_name);
				return 1;
				break;
			}
			case 'a' : 
			{
				// check in the given acton block;
				if(optind>=argc) print_usage(argv);
				string action_name = argv[optind++];
				if(optind>=argc) print_usage(argv);
				string tdl_fname = argv[optind];
				check_action_block(tdl_fname, action_name);
				return 1;
				break;
			}
			default :
				print_usage(argv);
		}
	}

	if(optind<argc) {
		string tdl_fname = argv[optind];
		check_all(tdl_fname);
	}

	return 1;
}
